package com.apes.fn.scm.retailOrder.service.account.retail;

import com.apes.fn.mdm.paint.PaintBusinessScope;
import com.apes.fn.mdm.paint.PaintBusinessScopeRepository;
import com.apes.fn.scm.retailOrder.service.account.RetailAccountData;
import com.apes.fn.scm.retailOrder.service.account.BackBatchAndSupplierService;
import com.apes.fn.server.servicePlan.model.ServicePlan;
import com.apes.fn.server.servicePlan.model.ServicePlanItem;
import com.apes.framework.util.LogicalUtil;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.ReflectUtil;
import com.apes.scm.account.tax.model.Tax;
import com.apes.scm.account.tax.service.TaxService;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.contract.service.ContractService;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherInventory;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.repository.VoucherInventoryRepository;
import com.apes.scm.voucher.service.BusinessType;
import com.apes.scm.voucher.service.VoucherType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 喷漆凭证服务（确认时间：2021-09-09）
 *  1、跨公司油漆业务时，直接写入凭证，不生成分销单
 *  2、跨公司喷漆经营范围，凭证生成的逻辑，
 *      一定是：PaintBusinessScope.dept 找 PaintBusinessScope.company 采购，PaintBusinessScope.company 找到 PaintBusinessScope.supplier 采购
 *
 * @Author wuq
 * @Date 2021-9-9
 */
@RetailAccount(value = "serverPaint", name = "同公司油漆")
@Service
public class ServerPaintVoucherService extends BackBatchAndSupplierService {

    @Autowired
    private ContractService contractService;
    @Autowired
    private TaxService taxService;
    @Autowired
    private VoucherInventoryRepository voucherInventoryRepository;
    @Autowired
    private PaintBusinessScopeRepository paintBusinessScopeRepository;

    /**
     * 根据服务方案生成油漆凭证
     *
     * @param retailAccountData List<ServicePlanItem>
     */
    public void process(RetailAccountData retailAccountData) {
        List<ServicePlanItem> items = retailAccountData.getServicePlanItems();

        ServicePlan servicePlan = items.get(0).getServicePlan();

        // 查询喷漆经营范围，判断是否为对账公司
        List<PaintBusinessScope> paintBusinessScopes =  paintBusinessScopeRepository.findByDept(servicePlan.getBelongDept().getId());
        PartyRole paintCompany = paintBusinessScopes.get(0).getCompany();       // 油漆对账公司
        PartyRole supplier = paintBusinessScopes.get(0).getSupplier();          // 油漆供应商

        if (servicePlan.getCompany().getId().equals(paintCompany.getId())) {
            // 为对账公司，直接找供应商采购
            paintPurchaseVoucher(supplier, servicePlan, items, false);
        } else {
            // 做跨公司采购
            crossPaintVoucher(paintCompany, supplier, servicePlan, items);
        }
    }

    private void paintPurchaseVoucher(PartyRole supplier, ServicePlan servicePlan, List<ServicePlanItem> servicePlanItems, boolean isCross) {
        Voucher voucher = new Voucher();
        voucher.setDept(servicePlan.getBelongDept());
        voucher.setCompany(servicePlan.getBelongDept().getCompany());
        voucher.setBusinessType(BusinessType.PURCHASE_ORDER);

        voucher.setPartner(supplier.getParty().getPartyRoleByType("Supplier"));
        Contract contract = contractService.getContract(voucher.getDept(), voucher.getPartner(), "distribution", "supplier", "内协油漆业务");
        voucher.setContract(contract);

        voucher.setInventoryMode(voucher.getContract().getCooperation().getInventoryMode());     //设置库存模式
        voucher.setAccountingMethod(voucher.getContract().getCooperation().getAccountingMethod());  // 核算方式
        voucher.setClassification(VoucherType.PAINT_PRODUCT);
        voucher.setCustomerExpand(servicePlan.getFnCustomerExpand().getId());

        voucher.setClerk(servicePlan.getConfirmUid()); //业务员
        voucher.setScene(servicePlan.getScene());
        voucher.setOrigin(servicePlan.getId());
        voucher.setOriginBusinessType(ServicePlan.class.getSimpleName());
        voucher.setSource(servicePlan.getId());
        voucher.setSourceBusinessType(ServicePlan.class.getSimpleName());

        PartyRole paintSupplier = voucher.getPartner();
        voucher.setVoucherItems(
                servicePlanItems.stream().map(item -> {
                    VoucherItem voucherItem = new VoucherItem();
                    ReflectUtil.copy(item, voucherItem, "product", "uom", "supplier");

                    voucherItem.setProductQty(item.getSaleQty());
                    voucherItem.setOriginItemId(item.getId());
                    voucherItem.setSourceItemId(item.getId());
                    voucherItem.setDiscount(0d);
                    voucherItem.setOwner(servicePlan.getBelongDept().getCompany());

                    Tax tax = taxService.getPurchaseTax(servicePlan.getBelongDept().getCompany(), paintSupplier, item.getProduct());  //供应商进项税
                    voucherItem.setTax(tax);

                    if(isCross){
                        voucherItem.setPriceUnit(item.getPaintPrice());
                    } else {
                        voucherItem.setPriceUnit(item.getPaintPurchasePrice());
                    }

                    return voucherItem;
                }).collect(Collectors.toSet()));

        voucher = invoke("voucher.create", MapUtil.mapped(voucher));

        // 回写明细批次
        sendServicePlanBathAndSupplier(voucher);

        /* 增加账单 */
        createFixedOriginInvoice(servicePlan, voucher);
    }

    private void createFixedOriginInvoice(ServicePlan servicePlan, Voucher voucher) {
        Map m = invoke("voucher.flow.invoice", MapUtil.mapped(voucher));
        m.put("origin", servicePlan.getSourceFrom());
        m.put("originBusinessType", ServicePlan.class.getSimpleName());
        invoke("invoice.create", m);
    }

    private void crossPaintVoucher(PartyRole paintCompany, PartyRole supplier, ServicePlan servicePlan, List<ServicePlanItem> servicePlanItems) {
        // 找油漆供应商采购凭证
        Voucher purVoucher = createPaintSupplierVoucher(paintCompany, supplier, servicePlan, servicePlanItems);

        // 对门店销售凭证
        createCrossPaintSaleVoucher(purVoucher, servicePlan, servicePlanItems);

        // 门店油漆采购凭证
        paintPurchaseVoucher(paintCompany, servicePlan, servicePlanItems, true);
    }

    private Voucher createPaintSupplierVoucher(PartyRole paintCompany, PartyRole supplier, ServicePlan servicePlan, List<ServicePlanItem> servicePlanItems){
        Voucher voucher = new Voucher();
        voucher.setBusinessType(BusinessType.PURCHASE_ORDER);
        voucher.setDept(getDept(paintCompany));
        voucher.setCompany(paintCompany);
        voucher.setPartner(supplier.getParty().getPartyRoleByType("Supplier"));

        Contract contract = contractService.getContract(voucher.getDept(), voucher.getPartner(), "distribution", "supplier", "内协油漆业务");
        voucher.setContract(contract);

        voucher.setInventoryMode(voucher.getContract().getCooperation().getInventoryMode());     //设置库存模式
        voucher.setAccountingMethod(voucher.getContract().getCooperation().getAccountingMethod());  // 核算方式
        voucher.setClassification(VoucherType.PAINT_PRODUCT);
        voucher.setCustomerExpand(servicePlan.getFnCustomerExpand().getId());

        voucher.setClerk(servicePlan.getConfirmUid()); //业务员
        voucher.setScene(servicePlan.getScene());
        voucher.setOrigin(servicePlan.getId());
        voucher.setOriginBusinessType(ServicePlan.class.getSimpleName());
        voucher.setSource(servicePlan.getId());
        voucher.setSourceBusinessType(ServicePlan.class.getSimpleName());

        PartyRole paintSupplier = voucher.getPartner();
        voucher.setVoucherItems(
                servicePlanItems.stream().map(item -> {
                    VoucherItem voucherItem = new VoucherItem();
                    ReflectUtil.copy(item, voucherItem, "product", "uom", "supplier");

                    voucherItem.setProductQty(item.getSaleQty());
                    voucherItem.setOriginItemId(item.getId());
                    voucherItem.setSourceItemId(item.getId());
                    voucherItem.setDiscount(0d);
                    voucherItem.setOwner(paintCompany);

                    Tax tax = taxService.getPurchaseTax(paintCompany, paintSupplier, item.getProduct());  //供应商进项税
                    voucherItem.setTax(tax);

                    voucherItem.setPriceUnit(item.getPaintPurchasePrice());     // 油漆采购价格
                    return voucherItem;
                }).collect(Collectors.toSet()));

        voucher = invoke("voucher.create", MapUtil.mapped(voucher));

        changeFrostQty(voucher, "服务单生成，油漆采购凭证");

        // 增加对供应的账单
        createFixedOriginInvoice(servicePlan, voucher);
        return voucher;
    }


    private void createCrossPaintSaleVoucher(Voucher purVoucher, ServicePlan servicePlan, List<ServicePlanItem> servicePlanItems){
        Voucher voucher = new Voucher();
        voucher.setBusinessType(BusinessType.SALE_ORDER);
        ReflectUtil.copy(purVoucher, voucher, "dept", "company", "clerk", "scene", "customerExpand");

        voucher.setPartner(servicePlan.getCompany().getParty().getPartyRoleByType("Customer")); // 门店公司
        Contract contract = contractService.getContract(voucher.getDept(), voucher.getPartner(), "distribution", "customer", "内协油漆业务");
        voucher.setContract(contract);

        voucher.setInventoryMode(voucher.getContract().getCooperation().getInventoryMode());     //设置库存模式
        voucher.setAccountingMethod(voucher.getContract().getCooperation().getAccountingMethod());  // 核算方式

        voucher.setSource(purVoucher.getId());
        voucher.setSourceBusinessType(Voucher.class.getSimpleName());
        voucher.setOrigin(servicePlan.getId());
        voucher.setOriginBusinessType(ServicePlan.class.getSimpleName());

        voucher.setVoucherItems(
                servicePlanItems.stream().map(item -> {
                    VoucherItem voucherItem = new VoucherItem();
                    ReflectUtil.copy(item, voucherItem, "product", "uom", "supplier");

                    voucherItem.setProductQty(item.getSaleQty());
                    voucherItem.setOriginItemId(item.getId());
                    voucherItem.setDiscount(0d);


                    Tax tax = taxService.getSaleTax(purVoucher.getCompany(), item.getProduct());
                    voucherItem.setTax(tax);

                    voucherItem.setOriginItemId(item.getId());
                    voucherItem.setSourceItemId(item.getId());
                    voucherItem.setOwner(purVoucher.getCompany());

                    voucherItem.setPriceUnit(item.getPaintPrice());     // 油漆采购价格
                    return voucherItem;
                }).collect(Collectors.toSet()));

        // 添加采购凭证批次以及供应商信息
        voucher.getVoucherItems().forEach(item -> {
            purVoucher.getVoucherItems().forEach(purchaseVoucherItem -> {

                VoucherInventory voucherInventory = voucherInventoryRepository.findByVoucherItem(purchaseVoucherItem).stream()
                        .findAny().orElseThrow(() -> new RuntimeException("找不到批次信息！"));

                if (item.getProduct().getId().equals(voucherInventory.getProduct().getId())) {
                    item.setInventoryBatch(voucherInventory.getInventoryBatch());
                    item.setSupplier(purchaseVoucherItem.getSupplier());
                }
            });
        });

        voucher = invoke("voucher.create", MapUtil.mapped(voucher));

        // 增加与基地账单
        createFixedOriginInvoice(servicePlan, voucher);
    }
}
